

/******************************************************************************
				I N C L U D E    F I L E
 *****************************************************************************/
#include	"stdafx.h"

#include	"Queue.h"



#define	_ERR_VAR_EQU_(VAR,VAL,PRINT_OUT)	\
{\
	if( VAR == VAL )\
	{\
		gm_printf(PRINT_OUT);\
	}\
}





//queue	return  information	 
enum{
	Q_RIGHT		= 0 ,
	ERR_Q_QNULL	= 1	,
	ERR_Q_QFULL	= 2	,
	ERR_Q_QHANDLE	= 3	,
	//ERR_Q_QLOCK	= 3	,
};	
	
/******************************************************************************
				T Y P E 	D E F I N I T I O N
 *****************************************************************************/
 
typedef	struct	QUEUE_S
{
	LPVOID	pBeginAdd	;
	DWORD  qCellSize ;
	DWORD  qCellNumber ;
	DWORD  qIn ;
	DWORD  qOut ;
	DWORD  qStatus ;
	HANDLE hMutex ;

}QUEUE_T,*LPQUEUE_T ;	
	
/**************************************************************************
				GLOBAL & STATIC    D A T A
 **************************************************************************/
static DWORD _s_MutexCount = 0 ;

static DWORD _s_GM_MutexCount = 0 ;

/******************************************************************************
			   F U N C T I O N    D E F I N I T I O N
 *****************************************************************************/		  

////////////////////////////////////////////////////////////
//	public
////////////////////////////////////////////////////////////

HANDLE	Q_Create( DWORD dwCellNumber , DWORD dwCellSize  ) 
{
	LPQUEUE_T pQueue ;	
	LPVOID	  pBuffer ;
//	DWORD     dwMutexCt ;

	pQueue = (LPQUEUE_T)LocalAlloc( LMEM_ZEROINIT, sizeof(QUEUE_T) + dwCellSize*dwCellNumber ) ;
	//pQueue=new QUEUE_T[dwCellNumber+1];
	if( NULL == pQueue )
	{
		gm_printf("\nERR:Q_Create:LocalAlloc( 0, sizeof(QUEUE_T) )\n");	
		return	NULL ;
	}
		
	pBuffer = (LPVOID)( (PBYTE)pQueue +sizeof(QUEUE_T) ) ;// (LPVOID)LocalAlloc( LMEM_ZEROINIT, dwCellSize*dwCellNumber ) ;

	pQueue->pBeginAdd 	= pBuffer ; 
	pQueue->qCellSize  	= dwCellSize ;
	pQueue->qCellNumber = dwCellNumber ;		
	pQueue->qIn   = 0 ;
	pQueue->qOut  = 0 ;	
	pQueue->qStatus = Q_B_NULL ;			
			
	//pQueue->hMutex = CreateMutex( (LPCSTR)NULL, dwMutexCt ) ; 

	pQueue->hMutex =CreateMutex(NULL, FALSE, (LPTSTR)NULL );

	
	_ERR_VAR_EQU_(pQueue->hMutex,NULL,	
				"ERR:Q_Create:CreateMutex:NULL\n");
	
	return	(HANDLE)pQueue ;	
}
	    	
BOOL	Q_Destroy( HANDLE hQueue ) 
{
	BOOL	ret ;

	ret = FALSE ;
	if( hQueue != NULL && hQueue != INVALID_HANDLE_VALUE )		
	{	
		HANDLE hMut = ((LPQUEUE_T)hQueue)->hMutex ;
		//	
		WaitForSingleObject( hMut, INFINITE ) ;  							 
			
		ret = (LocalFree((void *)hQueue)==NULL)  ;  
		if( FALSE == ret )
		{
			gm_printf("\r\nERR:Q_Destroy:LocalFree( (void *)hQueue ) ) \r\n") ;
		}
		ReleaseMutex(hMut);
		CloseHandle( hMut ) ;  
		//ReleaseMutex( hMut ) ; 				
	}
			
	return ret ;
}
  	        	       
BOOL	Q_Output( HANDLE hQueue, LPVOID  pCell ) 
{
	DWORD   ret ;
	LPVOID  pData ; 
	LPQUEUE_T pqueue  = (LPQUEUE_T)hQueue ; 

	if( hQueue != NULL && hQueue != INVALID_HANDLE_VALUE )
	{
		WaitForSingleObject( pqueue->hMutex, INFINITE ) ; 
		
		if( pqueue->qStatus & Q_B_NULL )
		{
			ret = ERR_Q_QNULL ;
		}
		else
		{
			pData = (LPVOID)((BYTE *)(pqueue->pBeginAdd) + pqueue->qOut*pqueue->qCellSize) ;
			memcpy( pCell, (const void *)pData, pqueue->qCellSize ) ; 

			//Q_Lock( hQueue ) ;		 
			pqueue->qOut++   ;      
			if( pqueue->qOut == pqueue->qCellNumber )
			{
				pqueue->qOut = 0 ;
			}
				
			if( pqueue->qOut == pqueue->qIn )
			{
				pqueue->qStatus |= Q_B_NULL ; 
			}

			pqueue->qStatus &= ~Q_B_FULL ;
			//Q_UnLock( hQueue ) ; 
			
			ret = Q_RIGHT;	
		}
		ReleaseMutex(pqueue->hMutex) ;
	}
	else
	{
		ret = ERR_Q_QHANDLE ;
	}

	return ( ret == Q_RIGHT ) ; 
}
	      	   
BOOL	Q_Input( HANDLE hQueue, LPVOID  pCell ) 
{
	DWORD  ret ;
	LPVOID  pData ; 
	LPQUEUE_T pQueue  = (LPQUEUE_T)hQueue ; 

	if( hQueue != NULL && hQueue != INVALID_HANDLE_VALUE )	
	{	
		
		WaitForSingleObject( pQueue->hMutex, INFINITE ) ; 
		
		if( pQueue->qStatus & Q_B_FULL )
		{
			ret = ERR_Q_QFULL ; 			
		}
		else	
		{
			pData = (LPVOID)( ((BYTE *)pQueue->pBeginAdd) + pQueue->qIn*pQueue->qCellSize ) ;
			memcpy( (void *)pData, pCell, pQueue->qCellSize ) ;
				
			pQueue->qIn++ ;		  
			if( pQueue->qIn == pQueue->qCellNumber )	
			{
				pQueue->qIn = 0 ;
			}
				
			if( pQueue->qIn == pQueue->qOut )
			{
				pQueue->qStatus |= Q_B_FULL ; 
			}

			pQueue->qStatus &= ~Q_B_NULL 	; 			
			
			ret = Q_RIGHT;		
		}
		ReleaseMutex( pQueue->hMutex ) ; 
	}
	else
	{
		ret = ERR_Q_QHANDLE ;
	}	

	return ( ret == Q_RIGHT ) ;	
}
	  	    		   
BOOL	Q_ClearAll( HANDLE hQueue ) 
{
	DWORD  ret ;
	LPQUEUE_T pQueue  = (LPQUEUE_T)hQueue ;	

	if( hQueue != NULL && hQueue != INVALID_HANDLE_VALUE )	
	{	
		WaitForSingleObject( pQueue->hMutex, INFINITE ) ; 
		pQueue->qIn   = 0 ;
		pQueue->qOut  = 0 ;	
		pQueue->qStatus = Q_B_NULL ;
		ReleaseMutex( pQueue->hMutex ) ; 
			
		ret = Q_RIGHT;
	}
	else
	{
		ret = ERR_Q_QHANDLE ;
	}	
	
	return ( ret == Q_RIGHT ) ;	
}
	  
DWORD	Q_GetStatus( HANDLE hQueue ) 
{
	return ((LPQUEUE_T)hQueue)->qStatus ; 
}



			

